/*
 * @Description: 立卷规则面板
 * @Author: Rfan
 * @Date: 2022-02-10 09:30:53
 * @LastEditTime: 2022-11-01 09:32:42
 */

import { FC, useCallback, useEffect, useState } from 'react';
import { Button, Form, Input, Select, Transfer } from 'antd';
import classNames from 'classnames/bind';
import update from 'immutability-helper';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { fetchMetadata } from '@/api/metadata';
import { useAutoFilingContext } from '../contexts/AutoFilingContext';
import { isNullObj } from '@/utils';
import { QUERY_METADATA_GROUP } from '@/view/system/Metadata/constants';
import TransferSelectItem from './TransferSelectItem';
import styles from '../styles/filingPane.module.scss';

const cx = classNames.bind(styles);

const { Option } = Select;

export type FilingPaneProps = {
  title: string;
  data: any;
};

// 规格列表
const pageSizeList = ['10mm', '15mm', '20mm', '25mm', '30mm', '40mm', '50mm'];

/**
 * @description: 立卷规则面板
 * @param {FilingPaneProps} props
 * @return {*}
 */
const FilingPane: FC<FilingPaneProps> = (props) => {
  const { title, data } = props;
  const { selectAT, commonRule, list, saveFilingFunc, addAutoFilling } = useAutoFilingContext();
  const [form] = Form.useForm();
  const [fieldList, setFieldList] = useState([]);
  // 穿梭框选中的项目key集合（穿梭框右侧）
  const [targetKeys, setTargetKeys] = useState<string[]>([]);
  // 穿梭框右侧渲染的项目列表，用于右侧项目渲染及提交提交
  const [targetItems, setTargetItems] = useState([]);
  // 选中项目的key集合
  const [selectedKeys, setSelectedKeys] = useState([]);
  // 保存按钮是否可点击标志
  const [saveFlag, setSaveFlag] = useState<boolean>(false);

  useEffect(() => {
    if (!isNullObj(selectAT)) {
      const fieldQuery = {
        metadataFieldType: QUERY_METADATA_GROUP,
        coordinate: {
          atType: selectAT.atType,
          atCode: selectAT.atCode,
          level: 1
        }
      };
      fetchMetadata(fieldQuery).then((res) => {
        console.log(res);
        setFieldList(
          res.data.map((item: any) => {
            item.key = item.id;
            item.sortType = item.sortType || 0;
            return item;
          })
        );
      });
    }
  }, [selectAT]);

  useEffect(() => {
    setTargetKeys(list.map((item: any) => item.fieldId));
    setTargetItems(
      list.map((item: any) => ({
        ...item,
        key: item.fieldId
      }))
    );
  }, [list]);

  useEffect(() => {
    form.resetFields();
    form.setFieldsValue(commonRule);
  }, [commonRule]);

  /**
   * @description: 提交表单，触发表单提交事件
   */
  const submitFunc = () => {
    form.submit();
  };
  /**
   * @description: 保存立卷规则
   * @param {any} values
   */
  const onFinish = (values: any) => {
    const arr = targetItems.map((item: any, idx: number) => ({
      required: item.required || false,
      sortNo: idx,
      fieldId: item.id || item.fieldId
    }));
    console.log('form finish', values, arr, isNullObj(commonRule));
    const query = JSON.parse(JSON.stringify(values));
    query.groupFieldList = arr;
    if (isNullObj(commonRule)) {
      addAutoFilling(query);
    } else {
      query.id = commonRule.id;
      saveFilingFunc(query).then(() => {
        setSaveFlag(false);
      });
    }
  };

  const onFinishFailed = (errorInfo: any) => {
    console.log('Failed:', errorInfo);
  };

  /**
   * @description: 选项在两栏之间转移时的回调函数,direction='right'时为增加，direction='left'时为删除
   * @param {any} nextTargetKeys 右侧框的key集合
   * @param {any} direction 数据移动方向
   * @param {any} moveKeys 移动的项目的key
   */
  const onChange = (nextTargetKeys: any, direction: any, moveKeys: any) => {
    setSaveFlag(true);
    setTargetKeys(nextTargetKeys);
    setTargetItems(
      nextTargetKeys.reverse().map((key: number | string) => {
        const fieldItem = fieldList.find((item) => item.id === key) || {};
        const listItem = list.find((lItem: any) => lItem.fieldId === key) || {};
        return { ...fieldItem, ...listItem };
      })
    );
  };

  /**
   * @description: 选中项发生改变时的回调函数，用于项目选中的展示，设置为 单选
   * @param {function} sourceSelectedKeys 左侧选中
   * @param {function} targetSelectedKeys 右侧选中
   */
  const onSelectChange = (
    sourceSelectedKeys: (number | string)[],
    targetSelectedKeys: (number | string)[]
  ) => {
    setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
  };

  /**
   * @description: 拖拽选中的条目触发，在此更新list
   */
  const moveSelect = useCallback((dragIndex: number, hoverIndex: number) => {
    console.log('moveSelect', dragIndex, hoverIndex);
    setTargetItems((state: any) =>
      update(state, {
        $splice: [
          [dragIndex, 1],
          [hoverIndex, 0, state[dragIndex]]
        ]
      })
    );
  }, []);

  /**
   * @description: 生成可拖拽列表
   */
  const renderSelect = useCallback((selectItem: any, listProps: any, index: number, onChange) => {
    return (
      <TransferSelectItem
        {...listProps}
        key={selectItem.key}
        index={index}
        item={selectItem}
        onChange={onChange}
        moveSelect={moveSelect}
      />
    );
  }, []);

  return (
    <div className={`auto-pane ${cx('filing-pane')}`}>
      <div className={cx('filing-header')}>
        <div className={cx('title')}>{title}</div>
        <div className={cx('opearte')}>
          <Button disabled={!saveFlag} onClick={submitFunc}>
            保存
          </Button>
        </div>
      </div>
      <div className={cx('container')}>
        <Form
          labelCol={{ span: 3 }}
          wrapperCol={{ span: 14 }}
          labelAlign={'left'}
          preserve={false}
          form={form}
          initialValues={data}
          size="small"
          onFinish={onFinish}
          onFinishFailed={onFinishFailed}
        >
          <Form.Item
            label="案卷分页数"
            name="pageNum"
            extra="分组中的页数（1~100000），把分组（自增字段中分组）相同的文件，按排序自动组合"
            rules={[{ required: true, message: '请输入案卷分页数' }]}
          >
            <Input
              onChange={() => {
                setSaveFlag(true);
              }}
            />
          </Form.Item>
          <Form.Item
            label="卷内序号长度"
            name="serialLength"
            extra={`卷内序号长度自动提取（如设置"100"，卷内需要长度为3，从001起始）。`}
            rules={[{ required: true, message: '请输入卷内序号长度' }]}
          >
            <Input
              onChange={() => {
                setSaveFlag(true);
              }}
            />
          </Form.Item>
          <Form.Item
            label="(卷)默认规格"
            name="defaultSpec"
            extra="卷（卷皮、卷盒）的尺寸规格选择，系统默认以案卷分页数指定"
            rules={[{ message: '请输入默认规格' }]}
          >
            <Select
              placeholder="请选择默认规格"
              onChange={() => {
                setSaveFlag(true);
              }}
            >
              {pageSizeList.map((name, idx) => (
                <Option key={idx} value={name}>
                  {name}
                </Option>
              ))}
            </Select>
          </Form.Item>
          <Form.Item label="自动组卷-分组设置" labelCol={{ span: 24 }} wrapperCol={{ span: 20 }}>
            <Transfer
              dataSource={fieldList}
              titles={['待选排序字段', '已选排序字段']}
              listStyle={{
                width: '50%',
                height: 320
              }}
              targetKeys={targetKeys}
              selectedKeys={selectedKeys}
              onChange={onChange}
              onSelectChange={onSelectChange}
              render={(item) => ({ label: item.field_desc, value: item.id })}
              showSelectAll={false}
            >
              {(listProps) => {
                if (listProps.direction === 'right') {
                  return (
                    <DndProvider backend={HTML5Backend}>
                      <div className="ant-transfer-list-content">
                        {targetItems.map((item: any, idx: number) =>
                          renderSelect(item, listProps, idx, setSaveFlag)
                        )}
                      </div>
                    </DndProvider>
                  );
                }
              }}
            </Transfer>
          </Form.Item>
        </Form>
      </div>
    </div>
  );
};

export default FilingPane;
